package com.bluesky.jwf.component.window;

import java.util.LinkedList;
import java.util.Queue;

import org.apache.log4j.Logger;

import com.bluesky.jwf.component.Component;
import com.bluesky.plum.uimodels.standard.UIComponent;

/**
 * the thread to handle events of all windows.
 * 
 * @author HZ00260
 * 
 */
public class WindowThread extends Thread {

	private static Logger log = Logger.getLogger(WindowThread.class);

	private ScreenWindow screenWindow;
	/**
	 * current window
	 */
	private Window currentWindow;
	/**
	 * current event queue
	 */
	private Queue<Event> currrentEventQueue;

	private Event currentEvent;
	/**
	 * updated by latest event
	 */
	private Thread servletThread;
	/**
	 * indicate the thread should quit all loops, and terminate itself.
	 */
	private boolean quit = false;

	public WindowThread(ScreenWindow screenWindow, Queue<Event> eventQueue,
			Thread servletThread) {
		this.screenWindow = screenWindow;
		this.currrentEventQueue = eventQueue;
		this.servletThread = servletThread;
	}

	private void handleEvent(Event event) {

		if (event.getComponentId() != null && event.getName() != null) {

			Component comp = (Component) screenWindow
					.getByIdInChildWindow(event.getComponentId());

			if (comp == null) {
				log.info("can not find component by id:"
						+ event.getComponentId());
				return;
			}
			// get the thread of the window. let it handle the event.

			// the active window is the window wrap the component
			currentWindow = (Window) comp.loadAncesterByClass(Window.class);

			comp.handleEvent(event.getName());

			refreshName();
		}
	}

	/**
	 * server for a new event queue, which normally bind with a new window(modal
	 * dialog).
	 * 
	 * @param q
	 */
	public void serveNewQueue(Queue<Event> q) {
		currrentEventQueue = q;

		// poll event, until got a EXIT_QUEUE event, exit.

		while (!quit) {
			log.debug("try to poll an event");
			Event e = currrentEventQueue.poll();

			if (e == null) {// no more event to be process, it is time to
				// render.

				log.debug("no more event in the queue, time to render");
				synchronized (servletThread) {
					servletThread.notify();
				}

				// wait until next event is coming.
				try {
					log.debug("to wait next event");
					synchronized (this) {
						wait();
					}

					log.debug("wait end, seems an event coming");
					continue;
				} catch (InterruptedException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
					log.debug("exception occur");
				}
			}

			if (e.isExitQueueEvent()) {
				log.debug("it is a EXIT event, quit the queue.");
				break;
			}

			// process the event
			log.debug("handle the event:" + e);
			handleEvent(e);
		}
	}

	public void refreshName() {
		this.setName("HTML Window Thread for \"" + currentWindow.getTitle()
				+ "\"");
	}

	@Override
	public void run() {
		log.debug("start thread");
		serveNewQueue(currrentEventQueue);
		log.debug("quit thread");
	}

	public synchronized void putEvent(Event event, Thread servletThread) {
		log.debug("Window:" + currentWindow.getTitle()
				+ " putEvent(): a event is put:" + event);
		this.servletThread = servletThread;

		currrentEventQueue.add(event);

		notify();
	}

	public synchronized void putExitQueueEvent() {
		log.debug("put a EXIT event");
		Event evt = new Event("", Event.EXIT_QUEUE);
		currrentEventQueue.add(evt);
		notify();
	}

	public boolean isQuit() {
		return quit;
	}

	public void setQuit(boolean quit) {
		this.quit = quit;
	}

}
